package c.x.jy.common.utils;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.Charset;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.UUID;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;

import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.ssl.SSLContextBuilder;
import org.apache.http.ssl.TrustStrategy;
import org.apache.http.util.EntityUtils;
import org.springframework.core.io.FileSystemResource;

import com.alibaba.druid.util.Base64;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;

import c.x.jy.common.mqtt.ReadConfig;


/**
 * http 工具类
 */
public class HttpUtil {

	public static String post(String requestUrl, String accessToken, String params, Map<String, String> headermap)
			throws Exception {
		String encoding = "UTF-8";
		if (requestUrl.contains("nlp")) {
			encoding = "GBK";
		}

		if (headermap == null) {
			headermap = new HashMap<>();
		}

		if (!headermap.containsKey("Content-Type")) {
			headermap.put("Content-Type", "application/x-www-form-urlencoded");
		}
		return HttpUtil.post(requestUrl, accessToken, params, encoding, headermap);
	}

	public static String post(String requestUrl, String params, Map<String, String> headermap) {
		String encoding = "UTF-8";
		if (requestUrl.contains("nlp")) {
			encoding = "GBK";
		}

		if (headermap == null) {
			headermap = new HashMap<>();
		}

		if (!headermap.containsKey("Content-Type")) {
			headermap.put("Content-Type", "application/x-www-form-urlencoded");
		}
		return HttpUtil.postGeneralUrl(requestUrl, params, encoding, headermap);
	}

	public static String post(String requestUrl, String accessToken, String params, String encoding,
			Map<String, String> headermap) {
		String url = requestUrl + "&accessToken=" + accessToken;
		return HttpUtil.postGeneralUrl(url, params, encoding, headermap);
	}

	public static String postGeneralUrl(String generalUrl, String params, String encoding,
			Map<String, String> headermap) {
		try {

			URL url = new URL(generalUrl);
			// 打开和URL之间的连接
			HttpURLConnection connection = (HttpURLConnection) url.openConnection();
			connection.setRequestMethod("POST");
			if (headermap==null||!headermap.containsKey("Content-Type"))
				// 设置通用的请求属性
				connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
			connection.setRequestProperty("Connection", "Keep-Alive");
			if (headermap != null) {
				headermap.forEach((k, v) -> {
					connection.setRequestProperty(k, v);
				});
			}
			connection.setUseCaches(false);
			connection.setDoOutput(true);
			connection.setDoInput(true);

			// 得到请求的输出流对象
			DataOutputStream out = new DataOutputStream(connection.getOutputStream());
			out.write(params.getBytes(encoding));// 这里有时候可以这样out.writeChars(params);
			out.flush();
			out.close();

			// 建立实际的连接
			connection.connect();
			// 获取所有响应头字段
			Map<String, List<String>> headers = connection.getHeaderFields();
			// 遍历所有的响应头字段
			for (String key : headers.keySet()) {
				System.err.println(key + "--->" + headers.get(key));
			}
			// 定义 BufferedReader输入流来读取URL的响应
			BufferedReader in = null;
			in = new BufferedReader(new InputStreamReader(connection.getInputStream(), encoding));
			String result = "";
			String getLine;
			while ((getLine = in.readLine()) != null) {
				result += getLine;
			}
			in.close();
			System.err.println("result:" + result);
			return result;

		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}
	
	public static String requestGetForHttp(String url){
		return requestGetForHttp(url, null );
	}
	public static String requestGetForHttp(String url,Map<String, String>headerMap){
		return requestGetForHttp(url, null, headerMap );
	}
	public static String requestGetForHttp(String url, Map<String, String> requestParams,Map<String, String>headerMap ){
		return requestForHttp(url, requestParams, headerMap, "get",null,null);
	}
	
	
	
	public static String requestPostForHttp(String url){
		return requestPostForHttp(url, null );
	}
	public static String requestPostForHttp(String url,Map<String, String>headerMap){
		return requestPostForHttp(url, null, headerMap );
	}

	public static String requestPostForHttp(String url, Map<String, String> requestParams,Map<String, String>headerMap ){
		return requestForHttp(url, requestParams, headerMap, "post",null,null);
	}
	
	
 
	
	/**
	 * @param url  请求地址
	 * @param requestParams  请求参数
	 * @param headerMap   请求头参数
	 * @param meoth  post or GET
	 * @param path  证书路径
	 * @param pwd    证书密钥
	 * @return
	 */
	public static String requestForHttp(String url, Map<String, String> requestParams, Map<String, String> headerMap,
			String meoth,String path,String pwd)     {
		String result = null;
		try{
		CloseableHttpClient httpClient;
		if (url.startsWith("https")) {
			httpClient = createSSLClientDefault(path,pwd);
		} else {
			httpClient = HttpClients.createDefault();
		}
		HttpRequestBase http;
		List<NameValuePair> params = new ArrayList<NameValuePair>();
		String param = "";
		if (requestParams != null) {
			Iterator<Entry<String, String>> it = requestParams.entrySet().iterator();
			// System.out.println(params.toString());
			while (it.hasNext()) {
				Entry<String, String> en = it.next();
				String key = en.getKey();
				String value = en.getValue();
				if (value != null) {
					params.add(new BasicNameValuePair(key, value));
					param = param + "&" + key + "=" + value;
				}
			}
		}
		if (meoth != null && meoth.equalsIgnoreCase("post")) {
			http = new HttpPost(url);
			((HttpPost) http).setEntity(new UrlEncodedFormEntity(params, "UTF-8"));
		} else {
			url = (url.contains("?") ? url : url + "?") + param;

			http = new HttpGet(url);
		}
		/** HttpPost */
		// HttpPost httpPost = new HttpPost(url);
		if (headerMap != null) {
			headerMap.forEach((k, v) -> {
				http.addHeader(k, v);
			});
		}
		if (headerMap==null||!headerMap.containsKey("Content-Type")) {
			http.addHeader("Content-Type", "application/x-www-form-urlencoded");
		}
		http.addHeader("Connection", "Keep-Alive");
		/** HttpResponse */
		CloseableHttpResponse httpResponse = httpClient.execute(http);
		try {
			HttpEntity httpEntity = httpResponse.getEntity();
			result = EntityUtils.toString(httpEntity, "utf-8");
			EntityUtils.consume(httpEntity);
			System.out.println(httpEntity);
		}catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				if (httpResponse != null) {
					httpResponse.close();
				}
			} catch (IOException e) {
				System.out.println("## release resouce error ##" + e);
			}
		}
		return result;
		}catch (Exception e) {
			e.printStackTrace();
		}
		return result;
	}

	//private static String path = "e:\\keytool\\sslclient.keystore";
	//private static char[] password = "aaaaaaa".toCharArray();

 
	/**
	 * 
	 * @param path  证收路径      path = "e:\\keytool\\sslclient.keystore";
	 * @param pwd   证书密钥  
	 * @return
	 * @throws UnrecoverableKeyException
	 * @throws CertificateException
	 * @throws FileNotFoundException
	 * @throws IOException
	 */
	public static CloseableHttpClient createSSLClientDefault(String path,String pwd)
			throws UnrecoverableKeyException, CertificateException, FileNotFoundException, IOException {
		try {
			SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy() {
				// 信任所有
				public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException {
					return true;
				}
			}).build();
            if(path!=null&&pwd!=null){
				KeyStore ts = KeyStore.getInstance("JKS");
				ts.load(new FileInputStream(path), pwd.toCharArray());
				TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
				tmf.init(ts);
				TrustManager[] tm = tmf.getTrustManagers();
				sslContext = SSLContext.getInstance("SSL");
				sslContext.init(null, tm, null);
            }
			SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext);

			return HttpClients.custom().setSSLSocketFactory(sslsf).build();
		} catch (KeyManagementException e) {
			e.printStackTrace();
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		} catch (KeyStoreException e) {
			e.printStackTrace();
		}
		return HttpClients.createDefault();
	}

	
	public static  ConnectionSocketFactory  createSSLConnectionSocketFactory (String path,String pwd)
			throws UnrecoverableKeyException, CertificateException, FileNotFoundException, IOException {
		try {
			SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy() {
				// 信任所有
				public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException {
					return true;
				}
			}).build();
            if(path!=null&&pwd!=null){
				KeyStore ts = KeyStore.getInstance("JKS");
				ts.load(new FileInputStream(path), pwd.toCharArray());
				TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
				tmf.init(ts);
				TrustManager[] tm = tmf.getTrustManagers();
				sslContext = SSLContext.getInstance("SSL");
				sslContext.init(null, tm, null);
            }
			SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext);

			return sslsf;
		} catch (KeyManagementException e) {
			e.printStackTrace();
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		} catch (KeyStoreException e) {
			e.printStackTrace();
		}
		return null;
	}
	
	//public static String url="http://47.112.194.147:18083/";
//	public static String url="http://www.dianduoke.com:18083/";
	//private  static String name="admin";
//	private static String pwd="public";


	public static String sendget( String path,Map<String,String> header) {
		return send(  null,  path,"get",header,false);
	}

	public static String sendget( String path) {
		return send(  null,  path,"get",null,true);
	}
	
	public static  String sendDelete( String path) {
		return send(  null,  path,"DELETE ",null,true);
	}
	
   public static String sendpost(JSONObject pushObject,String path) {
		return send(  pushObject,  path,"post",null,true);
	}
	
	public static String send(JSONObject pushObject,String path,String mehth,Map<String,String> header,boolean isauth) {
		CloseableHttpClient  client = HttpClients.createDefault();
        


		HttpClientContext context=new HttpClientContext();
		if(isauth) {
			//该网页需要认证（用户名、密码）
			CredentialsProvider credentialsProvider=new BasicCredentialsProvider();
			
			credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(ReadConfig.getMqttClientrUser(), ReadConfig.getMqttClientrPassword()));
			context.setCredentialsProvider(credentialsProvider);
		}
	
		
        HttpRequestBase post=null;
        if("post".equalsIgnoreCase(mehth) ){
        	post= new HttpPost( path.contains("http")?path:  ReadConfig.getMqttHttpHost()+path);
        	  System.out.println("要发送的数据" + JSON.toJSONString(pushObject));
            StringEntity myEntity = new StringEntity(JSON.toJSONString(pushObject),  ContentType.APPLICATION_JSON);// 构造请求数据
            ((HttpPost)post).setEntity(myEntity);// 设置请求体
        }else{
        	 System.out.println(path.contains("http")?path:   ReadConfig.getMqttHttpHost()+path);
        	post = new HttpGet(path.contains("http")?path:   ReadConfig.getMqttHttpHost()+path);
        }

        if(header!=null&&!header.isEmpty()){

			Iterator<Entry<String, String>>   it=	header.entrySet().iterator();

			for(;it.hasNext(); ){
				Entry <String, String> e=	it.next();
				post.addHeader(e.getKey(),e.getValue());
			}
		}
	//	if(isauth)
       // post.addHeader("Authorization", getHeader(ReadConfig.getMqttClientrUser(),ReadConfig.getMqttClientrPassword()));
		System.out.println(ReadConfig.getMqttClientrUser());
		System.out.println(ReadConfig.getMqttClientrPassword());
        String responseContent = null; // 响应内容
        CloseableHttpResponse response = null;
        try {
            response = client.execute(post,context);
            System.out.println(JSON.toJSONString(response));
            if (response.getStatusLine().getStatusCode() == 200) {
                HttpEntity entity = response.getEntity();
                responseContent = EntityUtils.toString(entity, "UTF-8");
            }
            System.out.println("responseContent:" + responseContent);
            return responseContent;
        } catch (ClientProtocolException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (response != null)
                    response.close();

            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                try {
                    if (client != null)
                        client.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
		return responseContent;
    }
	
	/**
     * 构造Basic Auth认证头信息
     * 
     * @return
     */
    private static String getHeader(String appid,String secret) {
        String auth =  appid +":" + secret;
        byte[] encodedAuth = Base64.altBase64ToByteArray(new String(auth.getBytes(Charset.forName("US-ASCII"))));
        String authHeader = "Basic " + new String(encodedAuth);
        return authHeader;
    }


	/**
	 * 网络上获取文 件  构造 本地临时文 件
	 * @param urlpath  网络URL
	 * @return
	 * @throws IOException
	 */
	public static FileSystemResource getFileUrlPathtoStream(String urlpath  ) throws IOException {
		File f= new File("../tmp/file");
		if(!f.exists()&&!f.isDirectory()){//判断文件目录是否存在
			f.mkdirs();
		}
		f = File.createTempFile(UUID.randomUUID().toString(), ".png", f);
		FileSystemResource  fileSystemResource=new FileSystemResource(f);
		OutputStream  os=	fileSystemResource.getOutputStream();
		BufferedInputStream bis = null;


		try {

			URL url = new URL(urlpath);
			HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
			httpURLConnection.setRequestMethod("GET");// 提交模式
			httpURLConnection.setConnectTimeout(10000);//连接超时 单位毫秒
			httpURLConnection.setReadTimeout(2000);//读取超时 单位毫秒
			// 获取URLConnection对象对应的输出流

			// 发送请求参数
			httpURLConnection.connect();
			bis = new BufferedInputStream(httpURLConnection.getInputStream());

			int len;
			byte[] arr = new byte[1024];
			while ((len = bis.read(arr)) != -1) {
				os.write(arr, 0, len);
				os.flush();
			}
			os.flush();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {

			if (os != null) {
				try {
					os.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}

			if (bis != null) {
				try {
					bis.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}


		}
		return fileSystemResource;
	}

}